package /*practicaplg.*/Analizadores;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import Analizadores.Estructuras.TokenList;
import Analizadores.Estructuras.Tipos.Token;
import Analizadores.Utilidades.Errores;

public class AnalizadorLexico {

   public static enum CategoriaLexica {
	   CLID,CLENT,CLREAL,CLCOM, CLCOMA,/*CLPUNTO,*/ CLPUNTOCOMA, /*CLEXP,*/ //Literales (Expresiones b�sicas) 
	   CLIN,CLOUT, // Operandos nivel 0 : in () out ()
	   CLASIG,//Operandos nivel 1 : = (asignacion)
	   CLMENOR,CLMAYOR,CLMENORIG,CLMAYORIG,CLIGUAL,CLDISTINTO,//Operandos nivel 2 : <,>,<=,>=,==,!=
	   CLOR,CLSUMA,CLRESTA,//Operandos nivel 3 : || (o l�gico),+,-
	   CLMUL,CLDIV,CLMOD,CLAND,//Operandos nivel 4 : *,/,%,&& (y l�gico)
	   CLCASTENT,CLCASTREAL,CLNEG,//Operandos nivel 5: (int),(real),!,-(unario) !!UNARIO EN RESTA
	   CLEOF,
	   CLTINT,CLTREAL,
	   CLPA,CLPC, //(,)
	   ERROR, ERRORLEXICO, //a�adido para que no abortemos la ejecucion si hay un token erroneo
	   //categorias lexicas segunda parte
	   CLIF, CLELSE, CLENDIF, CLTHEN, CLELSIF, CLWHILE, CLDO, CLENDWHILE, CLREC, CLENDREC, CLPOINTER,
	   CLNULL, CLRETURN, CLFUN, CLEND, CLTIPO, CLCORCHETEAB, CLCORCHETECER, CLALLOC, CLFREE, CLRETURNS,
	   CLCIRCUNFLEJO, CLAMPERSAN,CLPUNTO
   };
   
   private static enum Estado {STRECID, STRECENT, STRECREAL, STINICIO, STCOM, STPYC, STRCERO, STRECREALPUNTO,
	   STRECREALEXP, STRECREALFIN1, STRECREALFIN2, STRECREALFIN3, STRECMENOS, STRECREALPDECIMAL, STEOF,
	   STSUMA, STRECPA, STRECPC, STRECIGUAL, STRECDOBLEIGUAL, STRECMENOR,STRECMENORIGUAL, STRECMAYOR,
	   STRECMAYORIGUAL, STADMIR, STRECDISTINTO, STDISTINTO, STRESTA, STBARRA, STRECOR, STRECMUL, STRECDIV,
	   STRECMOD, STRECAMP, STRECAND, 
	   STRAMPA, //para tratar errores. Cuando encontremos uno, vamos a este estado, y nos lleva a inicio.
	   STERROR, STERRORLEXICO,
	   /*, STRECCASTENT, STRECCASTREAL, STRECI, STRECR, STRECN, STRECE, STRECT, 
	   STRECA, STRECL,*/
	/*segunda parte*/
	   STRECAMPERSAN, STRECCORAB, STRECCORCER, STRECCIRCUNFLEJO,STCOMA,STPUNTO
   
   };

   private Estado estado;
   
   private Map<String,/*Token*/CategoriaLexica> tablaReservadas;
   
   private StringBuffer lex;
   
   private int fila;
   
   private int columna;
   
   private TokenList lista;
   
   private Errores error;
   //private CategoriaLexica cat;
   
   private int sigCar;
   private /*Reader*/FileInputStream input;
  
   public AnalizadorLexico(/*Reader*/FileInputStream input,Errores er) throws IOException {
	      this.input = input;
//	      lista = new TokenList();
	      error = er;
		  sigCar = input.read();
		  lex = new StringBuffer();
		  construyeReservadas();
		  fila = 1;
		  columna = 0;
	   }

   public /*Token*/CategoriaLexica sigToken() throws IOException {
       estado = Estado.STINICIO;
	   iniciaLex();
	   while (true) {
	      switch(estado) {
		    case STINICIO: 
		      
		      if (hayLetra() || hayGuion()) transita(Estado.STRECID);
              else if (hayCero()) transita(Estado.STRCERO);
              else if (hayDigito()) transita(Estado.STRECENT);
              else if (hayIgnorable()) transitaIgnorando(Estado.STINICIO);
              else if (hayComentario()) transitaIgnorando(Estado.STCOM);
              else if (hayPyC()) transita(Estado.STPYC);
              else if (hayEof()) transita(Estado.STEOF);
              else if (haySuma()) transita(Estado.STSUMA);
              else if (hayResta()) transita(Estado.STRESTA);
              else if (hayPA()) transita(Estado.STRECPA); 
              else if (hayPC()) transita(Estado.STRECPC);
              else if (hayIgual()) transita(Estado.STRECIGUAL);
              else if (hayMenor()) transita(Estado.STRECMENOR);
              else if (hayMayor()) transita(Estado.STRECMAYOR);
              else if (hayAdmiracion()) transita(Estado.STADMIR);
              else if (hayBarra()) transita(Estado.STBARRA);
              else if (hayAsterisco()) transita(Estado.STRECMUL);
              else if (hayDivision()) transita(Estado.STRECDIV);
              else if (hayModulo()) transita(Estado.STRECMOD);
              else if (hayAmpersan()) transita(Estado.STRECAMP);
              else if (hayCorcheteAbierto()) transita(Estado.STRECCORAB);
              else if (hayCorcheteCerrado()) transita(Estado.STRECCORCER);
              else if (hayCircunflejo()) transita(Estado.STRECCIRCUNFLEJO);
              else if(hayComa())transita(Estado.STCOMA);
              else if(hayPunto()) transita(Estado.STPUNTO);
              else {
            	  transita(Estado.STERROR);//return error(); //RETURN A�ADIDO 			 
              }
              break;
            case STRECID:
              if (hayLetra() || hayDigito() || hayGuion()) transita(Estado.STRECID);
              else return tokenId();
              break;
            case STRCERO:
            	if (hayExp()) transita(Estado.STRECREALEXP);
            	else if (hayPunto()) transita(Estado.STRECREALPUNTO);
            	else return tokenEnt();
            	break;
            case STRECENT:
              if(hayDigito()) transita(Estado.STRECENT);
              else if (hayPunto()) transita(Estado.STRECREALPUNTO);
              else if (hayExp()) transita(Estado.STRECREALEXP);	  
              else return tokenEnt();
              break;
            case STRECREAL:
                if(hayDigito()) transita(Estado.STRECREAL);
                else if (hayPunto()) transita(Estado.STRECREAL);
                else if (hayExp()) transita(Estado.STRECREAL);	  
                else return tokenReal();
                break;
            case STCOM:
            	if (!hayFinLinea()) transitaIgnorando(Estado.STCOM);
            	else transitaIgnorando(Estado.STINICIO);
            	break;
            case STRECREALPUNTO:
            	if (hayCero()) transita(Estado.STRECREALPDECIMAL);
            	else if (hayDigito()) transita(Estado.STRECREALFIN1);
            	else transita(Estado.STERRORLEXICO); //A�ADIDO
            	break;
            case STRECREALPDECIMAL:
            	if (hayCero()) transita(Estado.STRECREALPDECIMAL);
            	else if (hayDigito()) transita(Estado.STRECREALFIN1);
            	else transita(Estado.STERRORLEXICO); // A�ADIDO
            	break;
            case STRECREALEXP:
            	if (hayMenos()) transita(Estado.STRECMENOS);
            	else if (hayCero()) transita(Estado.STRECREALFIN2);
            	else if (hayDigito()) transita(Estado.STRECREALFIN3);
            	else transita(Estado.STERRORLEXICO); // A�ADIDO
            	break;
            case STRECREALFIN1:
            	if (hayCero()) transita(Estado.STRECREALPDECIMAL);
            	else if (hayDigito()) transita(Estado.STRECREALFIN1);
            	else if (hayExp()) transita(Estado.STRECREALEXP);
            	else return tokenReal();
            	break;
            case STRECMENOS:
            	if (hayCero()) transita(Estado.STRECREALFIN2);
            	else if (hayDigito()) transita(Estado.STRECREALFIN3);
            	else transita(Estado.STERRORLEXICO); // A�ADIDO
            	break;
            case STRECREALFIN2:
            	return tokenReal();
            	//break;
            case STRECREALFIN3:
            	if (hayDigito()) transita(Estado.STRECREALFIN3);
            	else return tokenReal();
            	break;
            case STPYC:
            	return tokenPyC();
            case STEOF:
                return tokenEOF();
            case STSUMA:  
			    return tokenSuma();
            case STRECPA:
            	return tokenPA();
            case STRECPC:
            	return tokenPC();
            case STRECIGUAL:
            	if (hayIgual()) transita(Estado.STRECDOBLEIGUAL);
            	else return tokenIgual();
            	break;
            case STRECDOBLEIGUAL:
            	return tokenDobleIgual();
            case STRECMENOR:
            	if (hayIgual()) transita(Estado.STRECMENORIGUAL);
            	else return  tokenMenor();
            	break;
            case STRECMENORIGUAL:
            	return tokenMenorIgual();
            case STRECMAYOR:
            	if (hayIgual()) transita(Estado.STRECMAYORIGUAL);
            	else return  tokenMayor();
            	break;
            case STRECMAYORIGUAL:
            	return tokenMayorIgual();
            case STADMIR:
            	if(hayIgual()) transita(Estado.STDISTINTO);
            	else return tokenAdmiracion();
            	break;
            case STDISTINTO:
            	transita(Estado.STRECDISTINTO);
            	break;
            case STRECDISTINTO:
            	return tokenDistinto();
            case STRESTA:
            	return tokenResta();
            case STBARRA:
            	if (hayBarra()) transita(Estado.STRECOR);
            	else transita(Estado.STERRORLEXICO); // A�ADIDO
            	break;
            case STRECOR:
            	return tokenOr();
            case STRECMUL:
            	return tokenMul();
            case STRECDIV:
            	return tokenDiv();
            case STRECMOD:
            	return tokenMod();
            case STRECAMP:
            	if (hayAmpersan()) transita(Estado.STRECAND);
            	else /*transita(Estado.STERRORLEXICO);*/transita(Estado.STRECAMPERSAN); // A�ADIDO
            	break;
            case STRECAND:
            	return tokenAnd();
            /*case STERROR:
            	/*return*/ //error(); //RETURN A�ADIDO
            	//transita(Estado.STERRORLEXICO);
            case STERRORLEXICO:		               
            	return errorLexico(); //RETURN A�ADIDO
            case STERROR:
            	return error();
            case STRECAMPERSAN:
            	return tokenAmp();
            case STRECCORAB:
            	return tokenCorAb();
            case STRECCORCER: 
            	return tokenCorCer();
            case STRECCIRCUNFLEJO:
            	return tokenCircunflejo();  
            case STCOMA:
            	return tokenComa();
            case STPUNTO:
            	return punto();
		  }
	   }
	}   
   
   
   private /*Token*/CategoriaLexica tokenCircunflejo(){
	   return CategoriaLexica.CLCIRCUNFLEJO;
	   //return new Token(CategoriaLexica.CLDIV);
   }
   
  
   private /*Token*/CategoriaLexica tokenCorAb(){
	   return CategoriaLexica.CLCORCHETEAB;
	   //return new Token(CategoriaLexica.CLDIV);
   }
   
   private /*Token*/CategoriaLexica tokenCorCer(){
	   return CategoriaLexica.CLCORCHETECER;
	   //return new Token(CategoriaLexica.CLDIV);
   }
   
   private /*Token*/CategoriaLexica tokenAmp(){
	   return CategoriaLexica.CLAMPERSAN;
	   //return new Token(CategoriaLexica.CLDIV);
   }
   
   private /*Token*/CategoriaLexica tokenDiv(){
	   return CategoriaLexica.CLDIV;
	   //return new Token(CategoriaLexica.CLDIV);
   }
   
   private /*Token*/CategoriaLexica tokenMod(){
	   return CategoriaLexica.CLMOD;
	   //return new Token(CategoriaLexica.CLMOD);
   }
   
   private /*Token*/CategoriaLexica tokenAnd(){
	   return CategoriaLexica.CLAND;
	   //return new Token(CategoriaLexica.CLAND);
   }
   
   private /*Token*/CategoriaLexica tokenMul(){
	   return CategoriaLexica.CLMUL;
	   //return new Token(CategoriaLexica.CLMUL);
   }
 
   private /*Token*/CategoriaLexica tokenOr(){
	   return CategoriaLexica.CLOR;
	   //return new Token(CategoriaLexica.CLOR);
   }
   
   private /*Token*/CategoriaLexica tokenResta(){
	   return CategoriaLexica.CLRESTA;
	  //return new Token(CategoriaLexica.CLRESTA);
   }
   
   private /*Token*/CategoriaLexica tokenAdmiracion(){
	   return CategoriaLexica.CLNEG;
	   //return new Token(CategoriaLexica.CLNEG);
   }
   
   private /*Token*/CategoriaLexica tokenDistinto(){
	   return CategoriaLexica.CLDISTINTO;
	   //return new Token(CategoriaLexica.CLDISTINTO);
   }
   
   private /*Token*/CategoriaLexica tokenMayorIgual(){
	   return CategoriaLexica.CLMAYORIG;
	   //return new Token(CategoriaLexica.CLMAYORIG);
   }
   
   private /*Token*/CategoriaLexica tokenMayor(){
	   return CategoriaLexica.CLMAYOR;
	   //return new Token(CategoriaLexica.CLMAYOR);
   }
   
   private /*Token*/CategoriaLexica tokenMenorIgual(){
	   return CategoriaLexica.CLMENORIG;
	   //return new Token(CategoriaLexica.CLMENORIG);
   }
   
   private /*Token*/CategoriaLexica tokenMenor(){
	   return CategoriaLexica.CLMENOR;
	   //return new Token(CategoriaLexica.CLMENOR);
   }
   
   private /*Token*/CategoriaLexica tokenDobleIgual(){
	   return CategoriaLexica.CLIGUAL;
	   //return new Token(CategoriaLexica.CLIGUAL);
   }
   
   private /*Token*/CategoriaLexica tokenIgual() {
	   return CategoriaLexica.CLASIG;
	   //return new Token(CategoriaLexica.CLASIG);
   }
   
   private /*Token*/CategoriaLexica tokenPA() {
	   return CategoriaLexica.CLPA;   
	   //return new Token(CategoriaLexica.CLPA);
   }
   
   private /*Token*/CategoriaLexica tokenPC() {
	   return CategoriaLexica.CLPC;
	      //return new Token(CategoriaLexica.CLPC);
	   }
   
   private /*Token*/CategoriaLexica tokenSuma() {
	   return CategoriaLexica.CLSUMA;
	      //return new Token(CategoriaLexica.CLSUMA);
	   }
   
   private /*Token*/CategoriaLexica tokenEOF() {
	   return CategoriaLexica.CLEOF;
	      //return new Token(CategoriaLexica.CLEOF);
	   }
   private /*Token*/CategoriaLexica tokenComa() {
	   return CategoriaLexica.CLCOMA;
	      //return new Token(CategoriaLexica.CLEOF);
	   }
   
   private /*Token*/CategoriaLexica tokenPyC() {
	   return CategoriaLexica.CLPUNTOCOMA;
	      //return new Token(CategoriaLexica.CLPUNTOCOMA);
	   }
   
   private /*Token*/CategoriaLexica tokenEnt() {
	   return CategoriaLexica.CLENT;
      //return new Token(CategoriaLexica.CLENT,lex());
   }
   private /*Token*/CategoriaLexica tokenReal() {
	   return CategoriaLexica.CLREAL;
	      //return new Token(CategoriaLexica.CLREAL,lex());
	   }
   private CategoriaLexica punto(){
	   return CategoriaLexica.CLPUNTO;
   }
   private /*Token*/CategoriaLexica tokenId() {
      /*Token*/CategoriaLexica t = obtenReservada();
	  if (t == null) return /*new Token(*/CategoriaLexica.CLID/*,lex())*/;
      else return t;	  
   }
 /*  private Token tokenEof() {
      return new Token(CategoriaLexica.CLEOF);
   }*/
   private /*Token*/CategoriaLexica obtenReservada() {
	 String s = lex().toLowerCase(); //para no diferenciar entre mayus y minus, todas minus al comparar 
     return tablaReservadas.get(s); 
   } 
   private String lex() {

     return lex.toString().toLowerCase();

   }
   
   private void transita(Estado siguienteEstado) throws IOException {
      estado = siguienteEstado;
	  lex.append((char)sigCar);
	  sigCar = input.read();  
	  avanza();
   }
   private void transitaIgnorando(Estado siguienteEstado) throws IOException {
      estado = siguienteEstado;
	  sigCar = input.read(); 
	  avanza();
   }
   
   private void avanza(){
	   
		  if (sigCar == '\n') {fila++; columna=-1;}
		  else columna++;
   }
   private void iniciaLex() {
      lex.delete(0,lex.length());
   }
   private boolean hayLetra() {
     return sigCar >= 'a' && sigCar <= 'z' ||
	        sigCar >= 'A' && sigCar <= 'Z';			
   }
   private boolean hayDigito() {
     return sigCar >= '0' && sigCar <= '9';			
   }
 /*  private boolean hayEof() {
     return sigCar == -1; 		
   }*/
   private boolean hayIgnorable() {
     return sigCar == ' ' || sigCar == '\t' || sigCar == '\n' || sigCar == '\b' ||
	        sigCar == '\r'; 		
   }
   private boolean hayFinLinea() {
	     return sigCar == '\n'; 		
   }
  
   private boolean hayComentario() {
	     return sigCar == '@'; 		
   }
   private boolean hayPunto() {
	     return sigCar == '.'; 		
   }
   private boolean hayExp() {
	     return (sigCar == 'e' || sigCar == 'E'); 		
   }
   private boolean hayMenos() {
	     return sigCar == '-'; 		
 }
   private boolean hayGuion() {
	   return sigCar == '_';
   }
   private boolean hayPyC(){
	   return sigCar == ';';
   }
   private boolean hayEof(){
	   return sigCar == -1;
   }
   private boolean haySuma(){
	   return sigCar == '+';
   }
   private boolean hayPA(){
	   return sigCar == '(';
   }
   private boolean hayPC(){
	   return sigCar == ')';
   }
   
   private boolean hayIgual(){
	   return sigCar == '=';
   }
   
   private boolean hayMenor(){
	   return sigCar == '<';
   }
   
   private boolean hayMayor(){
	   return sigCar == '>';
   }
   
   private boolean hayAdmiracion(){
	   return sigCar == '!';
   }
   
   private boolean hayResta(){
	   return sigCar == '-';
   }
   
   private boolean hayBarra(){
	   return sigCar == '|';
   }
   
   private boolean hayAsterisco(){
	   return sigCar == '*';
   }
   
   private boolean hayDivision(){
	   return sigCar == '/';
   }
   
   private boolean hayModulo(){
	   return sigCar == '%';
   }
   
   private boolean hayAmpersan(){
	   return sigCar == '&';
   }
   
   private boolean hayCorcheteAbierto(){
	   return sigCar == '[';
   }
   
   private boolean hayCorcheteCerrado(){
	   return sigCar == ']';
   }
   
   private boolean hayCircunflejo(){
	   return sigCar == '^';
   }
   private boolean hayComa() {
	     return sigCar == ','; 		
 }

   private void construyeReservadas() {
     tablaReservadas = new HashMap<String,/*Token*/CategoriaLexica>();
	 tablaReservadas.put("int",/*new Token(*/CategoriaLexica.CLTINT/*)*/);
	 tablaReservadas.put("real",/*new Token(*/CategoriaLexica.CLTREAL/*)*/);
	 tablaReservadas.put("in",/*new Token(*/CategoriaLexica.CLIN/*)*/);
	 tablaReservadas.put("out",/*new Token(*/CategoriaLexica.CLOUT/*)*/);
	 /**SEGUNDA PARTE**/
	 tablaReservadas.put("if",/*new Token(*/CategoriaLexica.CLIF/*)*/);
	 tablaReservadas.put("else",/*new Token(*/CategoriaLexica.CLELSE/*)*/);
	 tablaReservadas.put("endif",/*new Token(*/CategoriaLexica.CLENDIF/*)*/);
	 tablaReservadas.put("then",/*new Token(*/CategoriaLexica.CLTHEN/*)*/);
	 tablaReservadas.put("elsif",/*new Token(*/CategoriaLexica.CLELSIF/*)*/);
	 tablaReservadas.put("while",/*new Token(*/CategoriaLexica.CLWHILE/*)*/);
	 tablaReservadas.put("do",/*new Token(*/CategoriaLexica.CLDO/*)*/);
	 tablaReservadas.put("endwhile",/*new Token(*/CategoriaLexica.CLENDWHILE/*)*/);
	 tablaReservadas.put("tipo",/*new Token(*/CategoriaLexica.CLTIPO/*)*/);
	 tablaReservadas.put("rec",/*new Token(*/CategoriaLexica.CLREC/*)*/);
	 tablaReservadas.put("endrec",/*new Token(*/CategoriaLexica.CLENDREC/*)*/);
	 tablaReservadas.put("pointer",/*new Token(*/CategoriaLexica.CLPOINTER/*)*/);
	 tablaReservadas.put("null",/*new Token(*/CategoriaLexica.CLNULL/*)*/);
	 tablaReservadas.put("return",/*new Token(*/CategoriaLexica.CLRETURN/*)*/);
	 tablaReservadas.put("fun",/*new Token(*/CategoriaLexica.CLFUN/*)*/);
	 tablaReservadas.put("end",/*new Token(*/CategoriaLexica.CLEND/*)*/);
	 tablaReservadas.put("alloc",/*new Token(*/CategoriaLexica.CLALLOC/*)*/);
	 tablaReservadas.put("free",/*new Token(*/CategoriaLexica.CLFREE/*)*/);
	 tablaReservadas.put("returns",/*new Token(*/CategoriaLexica.CLRETURNS/*)*/);
	 
   }
   
   private boolean hayCero() {
	     return sigCar == '0'; 		
   }
   
   private CategoriaLexica error() {
	 System.err.println("FILA: " + fila + " COLUMNA: " + columna);
     System.err.println("ERROR: Caracter no reconocido: "+ /*(char)sigCar*/ lex);
	 //System.exit(1);
	   return CategoriaLexica.ERROR;
   }
   private CategoriaLexica /*void*/ errorLexico() {
	   System.err.println("FILA: " + fila + " COLUMNA: " + columna);
	     System.err.println("ERROR: Expresion err�nea: "+ lex);
		 //System.exit(1);
	     return CategoriaLexica.ERROR/*LEXICO*/;
	   }
   
   public boolean esReservada(String lex){
	   return tablaReservadas.containsKey(lex);
   }
   
   public TokenList getLista(){
	   return lista;
   }
   
   public boolean parser() throws IOException {
	     // AnalizadorLexico al = new AnalizadorLexico(new InputStreamReader(System.in));
	   	  Token t1 = null;
	      Token t2 = null;
	      Token t3 = null;
	   	  int numVuelta = 1;
	   	  boolean correcto = true;
	   	  /*TokenList*/ lista = new TokenList();
		  CategoriaLexica t = sigToken();
		  boolean hayPA = false;
		  boolean anadidos = false;
		  Token tok = null;
		  boolean cast = false;
		  while (t/*.cat*/ != CategoriaLexica.CLEOF) {
			 tok = new Token(t,lex(),fila,columna);
			 
			 if (t == CategoriaLexica.CLPA)
				 hayPA = true;
			 if(cast==true){
				 cast = false;
				 lista.quitaToken();
			 }
			 else if (hayPA){

				 anadidos = false;
				 if (numVuelta % 3 == 1){
					 t1 =  tok;
				 }
				 else if (numVuelta % 3 == 2){
					 t2 =  tok;					 
				 }
				 else{
					 t3 =  tok;
					 //ya he leido 3 tokens, voy a ver si esta bien
					 if (t3.cat == CategoriaLexica.CLPC){
						 //tengo que comprobar el del medio
						 Token tcast = null;
						 if (t2.cat == CategoriaLexica.CLTINT){
							 lista.quitaToken();
							 lista.quitaToken();
							 tcast = new Token(CategoriaLexica.CLCASTENT,(t1.lex+t2.lex.toLowerCase()+t3.lex),fila,columna);
						 lista.anadir(tcast);
						 cast = true;
						 anadidos=true;
						 numVuelta = 0;
						 hayPA = false;
						  t1 = null;
						  t2 = null;
						  t3 = null;
						 //anadidos = true;
						 }//OK
						 else if (t2.cat == CategoriaLexica.CLTREAL){
							 lista.quitaToken();
							 lista.quitaToken();
							 tcast = new Token(CategoriaLexica.CLCASTREAL,(t1.lex+t2.lex.toLowerCase()+t3.lex),fila,columna);
							 lista.anadir(tcast);
							 cast = true;
							 anadidos=true;
							 numVuelta = 0;
							 hayPA = false;
							  t1 = null;
							  t2 = null;
							  t3 = null;
							 //anadidos = true;
						 }//OK
						 else{
							 //t1 = (, t3 = ), t2 lo que sea
							 //a�ado los 3, porque sea lo que sea no puede ser un casting
							 //lista.anadir(t1);
							 //lista.anadir(t2);
							 //lista.anadir(tok);
							 
							 anadidos=true;
							 numVuelta = 0;
							 hayPA = false;
							  t1 = null;
							  t2 = null;
							  t3 = null;
						 }
					 }
					 else{
						//t1 = (, t2,t3 lo que sea
						 if(t2.cat == CategoriaLexica.CLPA){
							 //lista.anadir(t1);
							 t1=t2;
							 t2=t3;
							 t3=null;
							 numVuelta = 2;
							 anadidos=false;
						 }
						 else if(t3.cat == CategoriaLexica.CLPA){
							 lista.anadir(t1);
							 lista.anadir(t2);
							 t1=t3;
							 t2=null;
							 t3=null;
							 numVuelta = 1;
							 anadidos=false;
						 }
						 else{
							//t1 = (, t2,t3 lo que sea, pero no (
							 //a�ado los 3, porque sea lo que sea no puede ser un casting
							 /*lista.anadir(t1);
							 lista.anadir(t2);
							 lista.anadir(t3);*/
							 
							 anadidos=true;
							 numVuelta = 0;
							 hayPA = false;
							  t1 = null;
							  t2 = null;
							  t3 = null;
						 }
						 
					 }
				 }
				 
				 numVuelta++;
			 }			 
			 //else{
				 //lista.anadir(tok);
			 //}
			 
			 if (tok.cat != CategoriaLexica.ERROR/*LEXICO*/){
				 lista.anadir(tok);
				 System.out.println("FILA: " + fila + " COLUMNA: " + columna + tok);
				 System.out.println(lista.toString());
			 }
			 else if(correcto){
				 error.escribeLexico(tok);
				 correcto = false;
			 }
			 t = sigToken();
			 
		  }
		  if (!anadidos){
			  	if (t1 != null)lista.anadir(t1);
				 if (t2 != null)lista.anadir(t2);
				 //if (t3 != null)lista.anadir(t3);
		  }
		  tok = new Token(t,lex(),fila,columna); 
		  lista.anadir(tok);
		  input.close();
		  return correcto;
	   }
   

   
   
}